<?php
/**
 * 框架核心入口文件
 * 环境检查，核心文件加载
 */

// 核心库目录(绝对路径)
define('CORE', dirname(__FILE__));
// 判断是否定义了APP_NAME, 如果没有定义APP_NAME 返回错误!
defined('APP_NAME') or exit("application config can not require!\n");

//-------------------------------------------------------------
// 基本常量, 项目路径
//-------------------------------------------------------------
define('PATH_ROOT',       substr(CORE, 0, -5) );
define('PATH_MODEL',      PATH_ROOT.'/'.APP_NAME.'/model');
define('PATH_CONTROL',    PATH_ROOT.'/'.APP_NAME.'/control');
define('PATH_CONFIG',     PATH_ROOT.'/'.APP_NAME.'/config');
define('PATH_CROND',      PATH_ROOT.'/'.APP_NAME.'/crond');
define('PATH_DATA',       PATH_ROOT.'/'.APP_NAME.'/data');
define('PATH_UPLOADS',    PATH_ROOT.'/uploads');
define('PATH_LOG',        PATH_DATA.'/log');
define('PATH_CACHE',      PATH_DATA.'/cache');
define('PATH_LIBRARY',    CORE.'/library');
define('PATH_SYS_CONFIG', CORE.'/config');
require_once(CORE.'/function.php');

//-------------------------------------------------------------
// 引入配置文件
//-------------------------------------------------------------
// 引入系统配置('绝对路径')
$sys_config  = load_config(PATH_SYS_CONFIG.'/inc_sys_config.php');
// 引入用户框架配置('决定路径')
$user_config = load_config(PATH_ROOT.'/'.APP_NAME.'/config/app_config.php'); 
// 合并配置
$config      = array_merge($sys_config, $user_config);

//-------------------------------------------------------------
// 开始设置并引入核心类
//-------------------------------------------------------------
// init start 系统初始化开始时间 记录下来, 方便统计php执行的时长
$_page_start_time = microtime(true);

// 严格开发模式, 将所有的错误都报出来
error_reporting( E_ALL );

// 开启register_globals会有诸多不安全可能性，因此强制要求关闭register_globals, 如果开启，变量不需要定义直接提交就可以获取
if ( ini_get('register_globals') )
{
    exit('php.ini register_globals must is Off! ');
}

// 设置时区
date_default_timezone_set( config('TIMEZONE_SET') );

// 设置开辟内存
ini_set('memory_limit', '1024M');

// 初始化是否debug安全IP， 这个标记会根据是否是安全IP来改变
$_debug_safe_ip = false;

// -----------------------------------------------------------
// 加载核心类库
// -----------------------------------------------------------
require CORE.'/util.php';
require CORE.'/cache.php';
require CORE.'/db.php';
require CORE.'/log.php';
require PATH_LIBRARY.'/debug/lib_debug.php';
//require CORE.'/wechat.php';

if (PHP_SAPI != 'cli') 
{
    require CORE.'/session.php';
    require CORE.'/req.php';
    req::init();
    require_once CORE.'/tpl.php';

    // 判断是否是安全IP， cli模式是没有IP的   
    if( in_array( util::get_client_ip(), config('SAFE_CLICENT_IP')) )
    {
        $_debug_safe_ip = true;
    }
}

// 设置严格的错误模式
ini_set('display_errors', 'On');

// 设置异常后调用函数
set_exception_handler('handler_debug_exception');

// 设置出错后调用的函数
set_error_handler('handler_debug_error', E_ALL);

 // 程序结束后执行的动作, 不管是不是因为报错结束的程序
register_shutdown_function('handler_php_shutdown');
function handler_php_shutdown()
{
    //调试模式执行时间
    global $_page_start_time, $_debug_safe_ip;
    if( ($_debug_safe_ip || config('DEBUG_MODE') === true) ) 
    {
        $et = sprintf('%0.4f', microtime(true) - $_page_start_time);
        show_debug_error($et);
    }

    log::save();
    if( defined('CLS_CACHE') ) 
    {
        cache::free();
    }
}

/**
 * run_controller 路由控制
 * 
 * @return void
 */
function run_controller()
{
    $ac = preg_replace("/[^0-9a-z_]/i", '', req::item('ac', 'index') );
    $ac = empty ( $ac ) ? $ac = 'index' : $ac;

    $ctl = 'ctl_'.preg_replace("/[^0-9a-z_]/i", '', req::item('ct', 'index') );
    $path_file = PATH_CONTROL . '/' . $ctl . '.php';

    if( file_exists( $path_file ) )
    {
        require $path_file;
    }
    else
    {
        throw new Exception ( "Contrl {$ctl}--{$path_file} is not exists!" );
    }
    if( method_exists ( $ctl, $ac ) === true )
    {
        $instance = new $ctl ( );
        $instance->$ac ();
    }
    else
    {
        throw new Exception ( "Method {$ctl}::{$ac}() is not exists!" );
    }
}

/**
 * 自动加载类库处理
 * 加载优先级 /core/library => 应用目录/model => 根目录/model
 * (如果不在这些位置, 则需自行手工加载，对于小型项目，也可以把model全放到library以减少类文件查找时间)
 * @return void
 */
function __autoload( $classname )
{
    $classname = preg_replace("/[^0-9a-z_]/i", '', $classname);
    // 其实我觉得这个没必要，毕竟已经引入的classname是不会走入到这里的
    if( class_exists ( $classname ) ) 
    {
        return true;
    }

    $classfile = $classname.'.php';

    if ( file_exists ( PATH_LIBRARY.'/'.$classfile ) )
    {
        require PATH_LIBRARY.'/'.$classfile;
    }
    else if( file_exists ( PATH_MODEL.'/'.$classfile ) )
    {
        require PATH_MODEL.'/'.$classfile;
    }
    else if (file_exists( PATH_ROOT ."/pub_model/".$classfile)) 
    {
        require PATH_ROOT ."/pub_model/".$classfile;
    }
    else
    {
        throw new Exception ( 'Error: Cannot find the '.$classname );
        return false;
    }
}
